package com.usian.wemedia.impl;


import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.usian.common.constants.WmNewsMessageConstants;
import com.usian.model.admin.dtos.NewsAuthDto;
import com.usian.model.common.dtos.PageResponseResult;
import com.usian.model.common.dtos.ResponseResult;
import com.usian.model.common.enums.AppHttpCodeEnum;
import com.usian.model.media.dtos.WmNewsDto;
import com.usian.model.media.dtos.WmNewsPageReqDto;
import com.usian.model.media.pojos.*;
import com.usian.utils.threadlocal.WmThreadLocalUtils;
import com.usian.wemedia.mapper.WmMaterialMapper;
import com.usian.wemedia.mapper.WmNewsMapper;
import com.usian.wemedia.mapper.WmNewsMaterialMapper;
import com.usian.wemedia.mapper.WmUserMapper;
import com.usian.wemedia.service.WmNewsService;
import org.apache.commons.lang3.StringUtils;
import org.apache.kafka.common.protocol.types.Field;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;


import java.util.*;
import java.util.stream.Collectors;


@Service
public class WmNewsServiceImpl extends ServiceImpl<WmNewsMapper, WmNews> implements WmNewsService {

    @Value("${fileServerUrl}")
    private String fileServerUrl;

    @Autowired
    private WmNewsMaterialMapper wmNewsMaterialMapper;

    @Autowired
    private WmMaterialMapper wmMaterialMapper;

    @Autowired
    private KafkaTemplate kafkaTemplate;

    @Autowired
    private WmNewsMapper wmNewsMapper;

    @Autowired
    private WmUserMapper wmUserMapper;

    @Autowired
    private WmNewsMessageConstants wmNewsMessageConstants;



    @Override
    public ResponseResult findList(WmNewsPageReqDto dto) {


//        1、校验参数
        if(dto == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        dto.checkParam();

//        2、构建条件
        QueryWrapper<WmNews> wrapper = new QueryWrapper<>();

        if (dto.getStatus()!=null){
            wrapper.lambda().eq(WmNews::getStatus,dto.getStatus());
        }


//        关键字
        if (StringUtils.isNotBlank(dto.getKeyword())){
            wrapper.lambda().like(WmNews::getTitle,dto.getKeyword());
        }

//        频道
        if (dto.getChannelId()!=null){
            wrapper.lambda().eq(WmNews::getChannelId,dto.getChannelId());
        }

//        发布时间
        if (dto.getBeginPubDate()!=null&&dto.getEndPubDate()!=null){
            wrapper.lambda().between(WmNews::getPublishTime,dto.getBeginPubDate(),dto.getEndPubDate());
        }

//        查询当前用户id
        WmUser wmUser = WmThreadLocalUtils.getUser();

        if (wmUser!=null){
            wrapper.lambda().eq(WmNews::getUserId,wmUser.getId());
        }

        wrapper.lambda().orderByDesc(WmNews::getCreatedTime);

//        3、封装条件
        Page page = new Page(dto.getPage(), dto.getSize());
        IPage iPage=page(page,wrapper);

        PageResponseResult responseResult = new PageResponseResult(dto.getPage(), dto.getSize(),(int) iPage.getTotal());


        responseResult.setData(iPage.getRecords());
        responseResult.setHost(fileServerUrl);

        return responseResult;
    }


    public static final Short COLLECT_MATERIAL = 1;//收藏
    public static final Short CANCEL_COLLECT_MATERIAL = 0;//收藏
    public static final String WM_NEWS_TYPE_IMAGE = "image";
    public static final Short WM_NEWS_NONE_IMAGE = 0;
    public static final Short WM_NEWS_SINGLE_IMAGE = 1;
    public static final Short WM_NEWS_MANY_IMAGE = 3;
    public static final Short WM_NEWS_TYPE_AUTO = -1;  //封面图片自动
    public static final Short WM_CONTENT_REFERENCE = 0;
    public static final Short WM_COVER_REFERENCE = 1;
    public static final short WM_NEWS_CONTENT_REFERENCE=1 ;//主图引用
    public static final short WM_NEWS_ENABLE_UP=9 ;//上架不能删除
    public static final short WM_NEWS_ENABLE_DOWN=0 ;//下架


    @Override
    public ResponseResult saveNews(WmNewsDto dto, Short isSubmit) {

//        1、校验参数
        if (dto == null || StringUtils.isBlank(dto.getContent())) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

//        2、保存wm_news

        WmNews wmNews = new WmNews();

        BeanUtils.copyProperties(dto,wmNews);
//        2、1判断无图自动设置封图
        if (WM_NEWS_TYPE_AUTO.equals(dto.getType())){
            wmNews.setType(null);
        }
//        2、2过滤图片格式
        if (dto.getImages()!=null&&dto.getImages().size()>0){
            String replace = dto.getImages().toString().replace("[", "").replace("]", "").replace(fileServerUrl, "").replace(" ", "");
            wmNews.setImages(replace);
        }

        this.saveWmNews(wmNews,isSubmit);

//        3、保存  文章内容图片和素材关系表
        String content = dto.getContent();
        List<Map> imageList = JSON.parseArray(content, Map.class);
        List<String> contentImageList = this.ectractUrlInfo(imageList);

//        提交的时候维护素材关系表
        if (isSubmit==WmNews.Status.SUBMIT.getCode()&&contentImageList.size()!=0) {
            ResponseResult result = this.saveRelativeInfoForContent(contentImageList, wmNews.getId());
            if (result.getCode() != 0) {
                return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);

            }
        }

//        4、保存封面与素材表
        if (isSubmit==WmNews.Status.SUBMIT.getCode()){
            ResponseResult result = this.saveRelativeInfoForCover(dto, contentImageList, wmNews);
            if (result.getCode()!=0){
                return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
            }
        }

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    @Override
    public ResponseResult findWmNewsById(Integer newId) {
        if(newId ==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        WmNews wmNews = this.getById(newId);
        ResponseResult result =ResponseResult.okResult(wmNews) ;
        result.setHost(fileServerUrl);
        return result;
    }

//    删除
    @Override
    public ResponseResult delNews(Integer id) {
        //1.检查参数
        if(id == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID,"文章Id不可缺少");
        }
        //2.获取数据
        WmNews wmNews = getById(id);
        if(wmNews == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST,"文章不存在");
        }

        //3.判断当前文章的状态  status==9  enable == 1
        if(wmNews.getStatus().equals(WmNews.Status.PUBLISHED.getCode()) && wmNews.getEnable().equals(WM_NEWS_ENABLE_UP)){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST,"文章已发布，不能删除");
        }

        //4.去除素材与文章的关系
        wmNewsMaterialMapper.delete(Wrappers.<WmNewsMaterial>lambdaQuery().eq(WmNewsMaterial::getNewsId,wmNews.getId()));

        //5.删除文章
        removeById(wmNews.getId());
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    @Override
    public ResponseResult downOrUp(WmNewsDto dto) {
        //1.检查参数
        if(dto == null || dto.getId() == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        //2.查询文章
        WmNews wmNews = getById(dto.getId());
        if(wmNews == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST,"文章不存在");
        }

        //3.判断文章是否发布
        if(!wmNews.getStatus().equals(WmNews.Status.PUBLISHED.getCode())){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST,"当前文章不是发布状态，不能上下架");
        }

        //4.修改文章状态，同步到app端（后期做）TODO
        if(dto.getEnable() != null && dto.getEnable() > -1 && dto.getEnable() < 2){

            if(wmNews.getArticleId()!=null){
                Map<String,Object> mesMap = new HashMap<>();
                mesMap.put("enable",dto.getEnable());
                mesMap.put("articleId",wmNews.getArticleId());
                kafkaTemplate.send(WmNewsMessageConstants.WM_NEWS_UP_OR_DOWN_TOPIC,JSON.toJSONString(mesMap));
            }

            update(Wrappers.<WmNews>lambdaUpdate().eq(WmNews::getId,dto.getId()).set(WmNews::getEnable,dto.getEnable()));
        }
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }




    @Override
    public List<Integer> findRelease() {

        List<WmNews> list = this.list(Wrappers.<WmNews>lambdaQuery().eq(WmNews::getStatus, 8).lt(WmNews::getPublishTime, new Date()));

        List<Integer> integerList = list.stream().map(WmNews::getId).collect(Collectors.toList());

        return integerList;
    }



    @Override
    public PageResponseResult findList(NewsAuthDto dto) {

//        if (dto==null){
////            return (PageResponseResult) PageResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
////        }
        dto.checkParam();

//        公式：分页从第几条开始  （当前页码-1）*每页条数=每页数据从第几条开始
        dto.setPage((dto.getPage()-1)*dto.getSize());
//        dto.setTitle("%"+dto.getTitle()+"%");

//        分页查询数据库
        List<WmNewsVo> wmNewsVoList = wmNewsMapper.findNewsByPage(dto);
        int count = wmNewsMapper.findListCount(dto);

        PageResponseResult responseResult = new PageResponseResult(dto.getPage(), dto.getSize(), count);
        responseResult.setData(wmNewsVoList);

        return responseResult;
    }

    @Override
    public WmNewsVo findOne(Integer id) {

        String authorName="";

        WmNews wmNews = wmNewsMapper.selectById(id);
        if (wmNews!=null){
//            查询作者信息
            WmUser wmUser = wmUserMapper.selectById(wmNews.getUserId());
            if (wmUser!=null){
                authorName = wmUser.getName();
            }
        }
        WmNewsVo wmNewsVo = new WmNewsVo();
        BeanUtils.copyProperties(wmNews,wmNewsVo);
        wmNewsVo.setAuthorName(authorName);

        return wmNewsVo;
    }


    //    处理封面图片
    private ResponseResult saveRelativeInfoForCover(WmNewsDto dto, List<String> contentImageList,WmNews wmNews){
        List<String> images = dto.getImages();
//        如果配置的是自动，才会分配封面图片
        if (dto.getType().equals(WM_NEWS_TYPE_AUTO)){
//            内容中的图片数量小于等于2,设置为单图
            if (contentImageList.size()>0&&contentImageList.size()<=2){
                wmNews.setType(WM_NEWS_SINGLE_IMAGE);
                images = contentImageList.stream().limit(1).collect(Collectors.toList());
            }else if (contentImageList.size()>2){
//                如果内容中的图片大于2，则设置为多图
                wmNews.setType(WM_NEWS_MANY_IMAGE);
                images=contentImageList.stream().limit(3).collect(Collectors.toList());
            }else {
                wmNews.setType(WM_NEWS_NONE_IMAGE);
            }
        }

//        过滤一下图片中的格式
        if (images != null && images.size() > 0) {
            wmNews.setImages(images.toString().replace("[", "")
                    .replace("]", "").replace(fileServerUrl, "")
                    .replace(" ", ""));

        }
        this.updateById(wmNews);

//        封面图片关系表
        List<String> materials = new ArrayList<>();
        for (String url : images) {
            materials.add(url.replace(fileServerUrl,""));
        }
        ResponseResult responseResult = this.saveRelativeInfoForContent(materials, wmNews.getId());
        if (responseResult.getCode()!=0){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }




    public void saveWmNews(WmNews wmNews,Short isSubmit){

        boolean flag=false;

        wmNews.setStatus(isSubmit);
        WmUser wmUser = WmThreadLocalUtils.getUser();
        if (wmUser!=null){
            wmNews.setUserId(wmUser.getId());
        }
        wmNews.setCreatedTime(new Date());
        wmNews.setSubmitedTime(new Date());
        wmNews.setEnable((short) 1);
        if (wmNews.getId()==null){
            flag = this.save(wmNews);
        }else {
//            修改   先删除关系表，在跟新主表
            LambdaQueryWrapper<WmNewsMaterial> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(WmNewsMaterial::getNewsId,wmNews.getId());
            wmNewsMaterialMapper.delete(lambdaQueryWrapper);
            flag = updateById(wmNews);
           }

//           文章保存或修改   wmnews  kafka  发一个消息
        if (flag){
            kafkaTemplate.send("news_topic",JSON.toJSONString(wmNews.getId()));
           }
        }



    private ResponseResult saveRelativeInfoForContent(List<String> contentImageList, Integer newsId){
//        先去素材库查询依赖
        QueryWrapper<WmMaterial> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().in(WmMaterial::getUrl,contentImageList);
        WmUser user = WmThreadLocalUtils.getUser();
        if (user!=null){
            queryWrapper.lambda().eq(WmMaterial::getUserId,user.getId());
        }
        List<WmMaterial> wmMaterialList = wmMaterialMapper.selectList(queryWrapper);


//        循环素材库集合，对比
        Map<String, Integer> uriIdMap = wmMaterialList.stream().collect(Collectors.toMap(WmMaterial::getUrl, WmMaterial::getId));

        List<String> materialsIds = new ArrayList<>();
        for (String url : contentImageList) {
            Integer id = uriIdMap.get(url);
            if (id==null){
//                图片不在素材库中
                return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
            }else {
//                图片在素材库中
                materialsIds.add(id.toString());
            }
        }

//        批量保存素材与文章关系表
        wmNewsMaterialMapper.saveRelationsByContent(materialsIds,newsId,WM_NEWS_CONTENT_REFERENCE);

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }




//    把内容中的图片路径提取出来放到 materials  List<String>
    public List<String> ectractUrlInfo(List<Map> imageList){
        List<String> materials = new ArrayList<>();
        for (Map map : imageList) {
            if (map.get("type").equals(WM_NEWS_TYPE_IMAGE)){
                String imageStr =(String) map.get("value");
                imageStr = imageStr.replace(fileServerUrl, "");
                materials.add(imageStr);
            }
        }
        return materials;
    }


}
